package com.example.message_queue;

import com.example.message_queue.common.MqException;
import com.example.message_queue.mqserver.core.MSGQueue;
import com.example.message_queue.mqserver.core.Message;
import com.example.message_queue.mqserver.datacenter.MessageFileManager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.util.ReflectionTestUtils;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.LinkedList;

/**
 * Created with Intellij IDEA.
 * Description;
 * User:TQ02
 * Data:2024-03-27
 * Time:16:38
 * Text：
 */
@SpringBootTest
public class MessageFileManger {
    private MessageFileManager messageFileManager = new MessageFileManager();

    @BeforeEach
    public void setup() throws IOException {
        //创建两个队列
        messageFileManager.createQueue("牛逼1");
        System.out.println("队列创建成功：牛逼1");
        messageFileManager.createQueue("牛逼2");
        System.out.println("队列创建成功：牛逼2");

    }
    @Test
    public void testCreateFiles(){
        //验证文件是否创建成功
        File queueDataFile1=new File("./data/"+"牛逼1"+"/queue_data.txt");
        Assertions.assertEquals(true,queueDataFile1.isFile());
        File queueStatFile1=new File("./data/"+"牛逼1"+"/queue_stat.txt");
        Assertions.assertEquals(true,queueStatFile1.isFile());


        File queueDataFile2=new File("./data/"+"牛逼2"+"/queue_data.txt");
        Assertions.assertEquals(true,queueDataFile2.isFile());
        File queueStatFile2=new File("./data/"+"牛逼2"+"/queue_stat.txt");
        Assertions.assertEquals(true,queueStatFile2.isFile());
    }
    @Test
    public void testReadWriteStat(){
        MessageFileManager.Stat stat=new MessageFileManager.Stat();
        stat.validCount=50;
        stat.totalCount=100;

        //使用Spring封装好的反射类
        ReflectionTestUtils.invokeMethod(messageFileManager,"writeStart","牛逼1",stat);
        //验证
        MessageFileManager.Stat stat1=ReflectionTestUtils.invokeMethod(messageFileManager,"readStat","牛逼1");
        Assertions.assertEquals(100,stat1.totalCount);
    }

    private MSGQueue createTestQueue(String queueName) {
        MSGQueue queue = new MSGQueue();
        queue.setName(queueName);
        queue.setDurable(true);
        queue.setAutoDelete(false);
        queue.setExclusive(false);
        return queue;
    }
    private Message createTestMessage(String content) {
        Message message = Message.createMessageWithId("testRoutingKey", null, content.getBytes());
        return message;
    }
    //验证发送数据是否正确
    @Test
    public void testSendMessage() throws IOException, MqException, ClassNotFoundException {
        //第一步：创建队列和消息
        MSGQueue queue=createTestQueue("牛逼1");
        Message message=createTestMessage("123456wdnwwndwinwicwcewc");
        //第二步 将消息放入
        messageFileManager.sendMessage(queue,message);

        MessageFileManager.Stat stat1=ReflectionTestUtils.invokeMethod(messageFileManager,"readStat","牛逼1");
        Assertions.assertEquals(1,stat1.totalCount);
        Assertions.assertEquals(1,stat1.totalCount);

        LinkedList<Message> t1=messageFileManager.loadAllMessageFromQueue("牛逼1");
        for(Message message1:t1){
            System.out.println(new String(message1.getBody()));
        }
    }
    //验证发送多次消息
    @Test
    public void testLoadAllMessageFromQueue() throws IOException, MqException, ClassNotFoundException {
        //第一步：创建队列和消息
        MSGQueue queue=createTestQueue("牛逼1");
        LinkedList<Message> except=new LinkedList<>();
        for(int i=0;i < 10;i++){
            Message message = createTestMessage("testMessage"+ i);
            messageFileManager.sendMessage(queue,message);
            except.add(message);
        }
        //读取消息
        LinkedList<Message> actual = messageFileManager.loadAllMessageFromQueue("牛逼1");
        Assertions.assertEquals(except.size(),actual.size());
        for(int i = 0;i< except.size();i++){
            Message ex=except.get(i);
            Message act = actual.get(i);
            Assertions.assertArrayEquals(ex.getBody(),act.getBody());
        }
    }
    //删除消息
    @Test
    public void testDeleteMessageFromQueue() throws IOException, MqException, ClassNotFoundException {
        MSGQueue queue = createTestQueue("牛逼1");
        LinkedList<Message> expected = new LinkedList<>();
        for (int i = 0; i < 10; i++) {
            Message message = createTestMessage("testMessage" + i);
            messageFileManager.sendMessage(queue, message);
            expected.add(message);
        }
        // 删除其中的三个消息
        messageFileManager.deleteMessage(queue, expected.get(7));
        messageFileManager.deleteMessage(queue, expected.get(8));
        messageFileManager.deleteMessage(queue, expected.get(9));
        // 对比这里的内容是否正确.
        LinkedList<Message> actualMessages = messageFileManager.loadAllMessageFromQueue("牛逼1");
        Assertions.assertEquals(7, actualMessages.size());
        for (int i = 0; i < actualMessages.size(); i++) {
            Message expectedMessage = expected.get(i);
            Message actualMessage = actualMessages.get(i);
            System.out.println("[" + i + "] actualMessage=" + actualMessage);
        }

    }


    //垃圾回收
    @Test
    public void testGC() throws IOException, MqException, ClassNotFoundException {
        MSGQueue queue = createTestQueue("牛逼1");
        LinkedList<Message> expected = new LinkedList<>();
        for (int i = 0; i < 100; i++) {
            Message message = createTestMessage("testMessage" + i);
            messageFileManager.sendMessage(queue, message);
            expected.add(message);
        }
        File befoFile=new File("./data/牛逼1/queue_data.txt");
        long size=befoFile.length();
        for(int i=0;i<100;i+=2){
            messageFileManager.deleteMessage(queue, expected.get(i));
        }
        //进行GC
        messageFileManager.getQueueNewPath("牛逼1");
         befoFile=new File("./data/牛逼1/queue_data.txt");
        long size2=befoFile.length();
        System.out.println(size+" "+size2);
        messageFileManager.gc(queue);


        LinkedList<Message> actual= messageFileManager.loadAllMessageFromQueue("牛逼1");
        for(int i=0; i < actual.size() ; i++){
            Message except = expected.get(i*2+1);
            Message actualMessage = actual.get(i);

            Assertions.assertEquals(except.getMessageId(), actualMessage.getMessageId());
            Assertions.assertEquals(except.getRoutingKey(), actualMessage.getRoutingKey());
            Assertions.assertEquals(except.getDeliverMode(), actualMessage.getDeliverMode());
            Assertions.assertArrayEquals(except.getBody(), actualMessage.getBody());
            Assertions.assertEquals(0x1, actualMessage.getIsValid());
        }
    }

    @AfterEach
    public void tearDown() throws IOException {
        messageFileManager.deleteQueueFiles("牛逼1");
        messageFileManager.deleteQueueFiles("牛逼2");
    }
}
